﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.SqlClient;
using Model;

namespace DAO
{
    public class ProdutoDAO
    {
        private String stringConexaoDB = ConfigurationManager.ConnectionStrings["ControlePedidoDB"].ToString();
        private static ProdutoDAO singleton = null;
        private SqlConnection conexaoDB = null;
        private SqlCommand comandoExecutar = null;

        private ProdutoDAO()
        {
            conexaoDB = new SqlConnection(stringConexaoDB);
        }

        public static ProdutoDAO getInstance()
        {
            if (singleton == null)
            {
                singleton = new ProdutoDAO();
            }

            return singleton;
        }

        public void inserir(Produto produto)
        {
            String SQL_INSERT = "INSERT INTO Produto (nome, descricao, valor_custo, valor, id_fornecedor, id_categoria, id_fabricante, qtde_estoque, qtde_minima)"
                                   + " VALUES ('" + produto.Nome + "', '" + produto.Descricao + "', '" + produto.ValorCusto
                                   + "', '" + produto.Valor + "', '" + produto.Fornecedor.Codigo + "', '" + produto.Categoria.Codigo
                                   + "', '" + produto.Fabricante.Codigo + "', '" + produto.QuantidadeEstoque + "', '" + produto.QuantidadeMinima + "')";
            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_INSERT, conexaoDB);

                comandoExecutar.ExecuteNonQuery();
            }
            catch (Exception cause)
            {
                throw new Exception("Problemas ao inserir o produto" + cause.Message);
            }
            finally
            {
                conexaoDB.Close();
            }

        }

        public void atualizar(Produto produto)
        {
            String SQL_UPDATE = "UPDATE Produto SET nome=@nome, descricao=@descricao, valor_custo=@valorcusto,"
                                + " valor=@valor, id_fornecedor=@fornecedor, id_categoria=@categoria,"
                                + " id_fabricante=@fabricante, qtde_estoque=@qtdeestoque, qtde_minima=@qtdeminima"
                                + " WHERE id_produto=@id";

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_UPDATE, conexaoDB);

                comandoExecutar.Parameters.Add(new SqlParameter("@nome", produto.Nome));
                comandoExecutar.Parameters.Add(new SqlParameter("@descricao", produto.Descricao));
                comandoExecutar.Parameters.Add(new SqlParameter("@valorcusto", produto.ValorCusto));
                comandoExecutar.Parameters.Add(new SqlParameter("@valor", produto.Valor));
                comandoExecutar.Parameters.Add(new SqlParameter("@fornecedor", produto.Fornecedor.Codigo));
                comandoExecutar.Parameters.Add(new SqlParameter("@categoria", produto.Categoria.Codigo));
                comandoExecutar.Parameters.Add(new SqlParameter("@fabricante", produto.Fabricante.Codigo));
                comandoExecutar.Parameters.Add(new SqlParameter("@qtdeestoque", produto.QuantidadeEstoque));
                comandoExecutar.Parameters.Add(new SqlParameter("@qtdeminima", produto.QuantidadeMinima));
                comandoExecutar.Parameters.Add(new SqlParameter("@id", produto.Codigo));

                comandoExecutar.ExecuteNonQuery();

            }
            catch (Exception cause)
            {
                throw cause;
            }
            finally
            {
                conexaoDB.Close();
            }

        }

        public List<Produto> recuperarProdutos(Produto produto) 
        {
            List<SqlParameter> parametros = new List<SqlParameter>();
            List<Produto> produtosRecuperados = new List<Produto>();
            Produto auxiliar = null;
            String SQL_BUSCA = "SELECT id_produto, nome FROM Produto WHERE ";
            SqlDataReader resultadoBusca = null;

            if (produto.Codigo > 0) {
                SQL_BUSCA += "id_produto = @id";

                parametros.Add(new SqlParameter("@id", produto.Codigo));
            }

            if (produto.Nome != null && !produto.Nome.Equals("")) {

                if (SQL_BUSCA.Contains('@'))
                {
                    SQL_BUSCA += "AND ";
                }
                else { 
                
                }
                SQL_BUSCA += "nome LIKE @nome";
                parametros.Add(new SqlParameter("@nome", "%" + produto.Nome + "%"));
            }

            try {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_BUSCA, conexaoDB);

                foreach (var parametro in parametros)
                {
                    comandoExecutar.Parameters.Add(parametro);
                }

                resultadoBusca = comandoExecutar.ExecuteReader();

                while (resultadoBusca.Read()) {
                    auxiliar = new Produto();

                    auxiliar.Codigo = Int32.Parse(resultadoBusca["id_produto"].ToString());
                    auxiliar.Nome = resultadoBusca["nome"].ToString();

                    produtosRecuperados.Add(auxiliar);
                }

            }catch(Exception cause){
                throw new Exception("A busca não trouxe nenhum resultado - causa: " + cause.Message);
            }finally{
                conexaoDB.Close();
            }

            return produtosRecuperados;
        }

        public Produto consultar(Produto produto)
        {
            SqlDataReader resultadoConsulta = null;
            String SQL_RETRIEVE = "SELECT nome, descricao, valor_custo, valor,"
                                + " id_fornecedor, id_categoria, id_fabricante,"
                                + " qtde_estoque, qtde_minima FROM Produto WHERE id_produto=@id";

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_RETRIEVE, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", produto.Codigo));

                resultadoConsulta = comandoExecutar.ExecuteReader();

                while (resultadoConsulta.Read())
                {
                    produto.Nome = resultadoConsulta["nome"].ToString();
                    produto.Descricao = resultadoConsulta["descricao"].ToString();
                    produto.Valor = decimal.Parse(resultadoConsulta["valor"].ToString());
                    produto.ValorCusto = decimal.Parse(resultadoConsulta["valor_custo"].ToString());
                    produto.Fornecedor = new Fornecedor(int.Parse(resultadoConsulta["id_fornecedor"].ToString()));
                    produto.Categoria = new Categoria(int.Parse(resultadoConsulta["id_categoria"].ToString()));
                    produto.Fabricante = new Fabricante(int.Parse(resultadoConsulta["id_fabricante"].ToString()));
                    produto.QuantidadeMinima = int.Parse(resultadoConsulta["qtde_minima"].ToString());
                    produto.QuantidadeEstoque = int.Parse(resultadoConsulta["qtde_estoque"].ToString());
                }

            }
            catch (Exception cause)
            {
                Console.WriteLine("Erro na consulta: {0}", cause.Message);
            }
            finally
            {
                conexaoDB.Close();
            }

            return produto;
        }

        public void excluir(Produto produto)
        {
            String SQL_DELETE = "DELETE FROM Produto WHERE id_produto=@id";

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_DELETE, conexaoDB);

                comandoExecutar.Parameters.AddWithValue("@id", produto.Codigo);

                comandoExecutar.ExecuteNonQuery();

            }
            catch (Exception cause)
            {
                Console.WriteLine("Erro na exclusão do produto, {0}", cause.Message);
            }
            finally
            {
                conexaoDB.Close();
            }

        }

        public bool verificarDescricaoProduto(Produto produto)
        {
            bool validacao = false;
            String SQL_CONSULTA = "SELECT id_produto FROM Produto WHERE nome=@nomeProduto";

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@nomeProduto", produto.Nome));

                SqlDataReader resultadosObtidos = comandoExecutar.ExecuteReader();

                validacao = resultadosObtidos.HasRows;
            }
            catch (Exception)
            {
                validacao = false;
            }
            finally
            {
                conexaoDB.Close();
            }

            return validacao;
        }

        public int verificaQuantidadeEstoque(Produto produto) 
        {
            String SQL_CONSULTA = "SELECT qtde_estoque FROM Produto WHERE id_produto=@id";
            int quantidadeEstoque = 0;

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", produto.Codigo));

                SqlDataReader resultadosObtidos = comandoExecutar.ExecuteReader();

                if (resultadosObtidos.Read()) {
                    quantidadeEstoque = Int32.Parse(resultadosObtidos["qtde_estoque"].ToString());
                }
            }
            catch (Exception cause)
            {
                throw cause;
            }
            finally
            {
                conexaoDB.Close();
            }
            
            return quantidadeEstoque;
        }

        public bool verificaPedidos(Produto produto) {
            bool validacao = false;
            String SQL_CONSULTA = "SELECT id_pedido FROM Item_Pedido WHERE id_produto=@id";

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", produto.Codigo));

                SqlDataReader resultadosObtidos = comandoExecutar.ExecuteReader();

                validacao = resultadosObtidos.HasRows;
            }
            catch (Exception)
            {
                validacao = false;
            }
            finally
            {
                conexaoDB.Close();
            }

            return validacao;
        }

        public bool hasProdutoCadastrado(Fabricante fabricante) {
            bool validacao = false;

            String SQL_CONSULTA = "SELECT id_produto FROM Produto WHERE id_fabricante=@id";
            SqlDataReader resultadoBusca = null;

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", fabricante.Codigo));

                resultadoBusca = comandoExecutar.ExecuteReader();

                validacao = resultadoBusca.HasRows;
            }
            catch (Exception cause) 
            {
                throw cause;
            }finally
            {
                conexaoDB.Close();
            }

            return validacao;
        }

        public bool hasProdutoCadastrado(Categoria categoria)
        {
            bool validacao = false;

            String SQL_CONSULTA = "SELECT id_produto FROM Produto WHERE id_categoria = @id ";
            SqlDataReader resultadoBusca = null;

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", categoria.Codigo));

                resultadoBusca = comandoExecutar.ExecuteReader();

                validacao = resultadoBusca.HasRows;
            }
            catch (Exception cause)
            {
                throw cause;
            }
            finally
            {
                conexaoDB.Close();
            }

            return validacao;
        }

        public bool hasProdutoCadastrado(Fornecedor fornecedor)
        {
            bool validacao = false;

            String SQL_CONSULTA = "SELECT id_produto FROM Produto WHERE id_fornecedor=@id";
            SqlDataReader resultadoBusca = null;

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", fornecedor.Codigo));

                resultadoBusca = comandoExecutar.ExecuteReader();

                validacao = resultadoBusca.HasRows;
            }
            catch (Exception cause)
            {
                throw cause;
            }
            finally
            {
                conexaoDB.Close();
            }

            return validacao;
        }

        public List<Produto> recuperarTodosProdutos() 
        {
            List<Produto> produtosCadastrados = new List<Produto>();
            String SQL_CONSULTA = "SELECT id_produto, nome FROM Produto";
            SqlDataReader resultadoConsulta = null;
            Produto auxiliar = null;

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);

                resultadoConsulta = comandoExecutar.ExecuteReader();

                while (resultadoConsulta.Read())
                {
                    auxiliar = new Produto();

                    auxiliar.Codigo = int.Parse(resultadoConsulta["id_produto"].ToString());
                    auxiliar.Nome = resultadoConsulta["nome"].ToString();

                    produtosCadastrados.Add(auxiliar);
                }
            }
            catch (Exception)
            {
                throw new Exception("A busca de produtos não retornou nenhum resultado!");
            }
            finally 
            {
                conexaoDB.Close();
            }

            return produtosCadastrados;
        }

        public decimal recuperarValorProduto(Produto produto) {
            decimal valorProduto = 0;
            String SQL_CONSULTA = "SELECT valor FROM Produto WHERE id_produto=@id";
            SqlDataReader resultadoBusca = null;

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_CONSULTA, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@id", produto.Codigo));

                resultadoBusca = comandoExecutar.ExecuteReader();

                while (resultadoBusca.Read()) 
                {
                    valorProduto = decimal.Parse(resultadoBusca["valor"].ToString());
                }
            }
            catch(Exception cause){
                throw new Exception("Problemas ao recuperar o valor do produto - " + cause.Message);                
            }
            finally
            {
                conexaoDB.Close();
            }

            return valorProduto;
        }

        public void atualizarQuantidadeEstoque(int codigoProduto, int quantidade) {
            String SQL_UPDATE = "UPDATE Produto SET qtde_estoque = @quantidade WHERE id_produto = @id";

            try
            {
                conexaoDB.Open();

                comandoExecutar = new SqlCommand(SQL_UPDATE, conexaoDB);
                comandoExecutar.Parameters.Add(new SqlParameter("@quantidade", quantidade));
                comandoExecutar.Parameters.Add(new SqlParameter("@id", codigoProduto));

                comandoExecutar.ExecuteNonQuery();
            }
            catch (Exception) 
            {
                throw new Exception("Problemas na atualização da quantidade de estoque!");
            }
            finally
            {
                conexaoDB.Close();
            }
        }

    }
}